/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include <stdio.h>
#include "task.h"
#include "usart.h"
#include "sht20.h"
#include <string.h>
#include "tvoc_co2_sensor.h"
#include "fram.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
extern TVOC_CO2_Data_t tvoc_co2_data;
extern SHT20_Data_t sht20_data;

void SHT20_Task(void *argument);
void TVOC_CO2_SensorTask(void *argument);
void ZigBee_UART_Task(void *argument);
void ZigBee_UART_Send(uint8_t *data, uint16_t len);
void DataStorageTask(void *argument);
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* Create SHT20_Task */
  xTaskCreate(SHT20_Task, "sht20_task", 512, NULL, osPriorityNormal, NULL);
  /* Create TVOC_CO2_SensorTask */
  xTaskCreate(TVOC_CO2_SensorTask, "tvoc_co2_task", 512, NULL, osPriorityNormal, NULL);
  /* Create DataStorageTask */
  xTaskCreate(DataStorageTask, "datastoragetask", 512, NULL, osPriorityNormal, NULL);
  xTaskCreate(ZigBee_UART_Task, "zigbee_uart_task", 256, NULL, osPriorityNormal, NULL);
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  char buf[32];

  /* Infinite loop */
  for(;;)
  {
    OLED_Clear();

    // Display SHT20 data
    OLED_PrintString(0, 0, "Temp:", OLED_COLOR_NORMAL);
    if (sht20_data.data_valid) {
        sprintf(buf, "%.1f C", sht20_data.temperature);
        OLED_PrintString(6 * 8, 0, buf, OLED_COLOR_NORMAL);
    } else {
        OLED_PrintString(6 * 8, 0, "N/A", OLED_COLOR_NORMAL);
    }

    OLED_PrintString(0, 1, "Hum:", OLED_COLOR_NORMAL);
    if (sht20_data.data_valid) {
        sprintf(buf, "%.1f %%", sht20_data.humidity);
        OLED_PrintString(6 * 8, 1, buf, OLED_COLOR_NORMAL);
    } else {
        OLED_PrintString(6 * 8, 1, "N/A", OLED_COLOR_NORMAL);
    }

    // Display TVOC data
    OLED_PrintString(0, 2, "TVOC:", OLED_COLOR_NORMAL);
    if (tvoc_co2_data.data_valid) {
        sprintf(buf, "%.3f mg/m3", tvoc_co2_data.tvoc_mg_m3);
        OLED_PrintString(6 * 8, 2, buf, OLED_COLOR_NORMAL);
    } else {
        OLED_PrintString(6 * 8, 2, "N/A", OLED_COLOR_NORMAL);
    }
    
    // Display CH2O data
    OLED_PrintString(0, 3, "CH2O:", OLED_COLOR_NORMAL);
    if (tvoc_co2_data.data_valid) {
        sprintf(buf, "%.3f mg/m3", tvoc_co2_data.ch2o_mg_m3);
        OLED_PrintString(6 * 8, 3, buf, OLED_COLOR_NORMAL);
    } else {
        OLED_PrintString(6 * 8, 3, "N/A", OLED_COLOR_NORMAL);
    }

    // Display CO2 data
    OLED_PrintString(0, 4, "CO2:", OLED_COLOR_NORMAL);
    if (tvoc_co2_data.data_valid) {
        sprintf(buf, "%.3f pp", tvoc_co2_data.co2_mg_m3);
        OLED_PrintString(6 * 8, 4, buf, OLED_COLOR_NORMAL);
    } else {
        OLED_PrintString(6 * 8, 4, "N/A", OLED_COLOR_NORMAL);
    }

    OLED_ShowFrame();
    vTaskDelay(pdMS_TO_TICKS(1000)); // Update display every 1 second
  }
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void SHT20_Task(void *argument)
{

    SHT20_Init();
    
    for(;;)
    {

        if (SHT20_Read_Data() != HAL_OK) {
            printf("SHT20: Read data failed\r\n");
        }
        

        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

void TVOC_CO2_SensorTask(void *argument)
{

    TVOC_CO2_Init();
    
    for(;;)
    {

        if (TVOC_CO2_Read_Data() != HAL_OK) {
            printf("TVOC-CO2: Read data failed\r\n");
        }
        

        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

void DataStorageTask(void *argument)
{
    // 初始化FRAM
    if (!FRAM_Init()) {
        printf("FRAM initialization failed\r\n");
        vTaskDelete(NULL);
        return;
    }
    
    for(;;)
    {
        // 创建传感器数据结构
        sensor_data_t sensor_data;
        
        // 获取当前时间
        sensor_data.timestamp = HAL_GetTick();
        
        // 填充传感器数据
        if (sht20_data.data_valid) {
            sensor_data.temperature = sht20_data.temperature;
            sensor_data.humidity = sht20_data.humidity;
        } else {
            sensor_data.temperature = -999.0f;
            sensor_data.humidity = -999.0f;
        }
        
        // 保存传感器数据到FRAM
        if (FRAM_Save24HourData(&sensor_data)) {
            printf("Data saved: T=%.1f, H=%.1f, CO2=%d\r\n", 
                   sensor_data.temperature, sensor_data.humidity, 
                   sensor_data.co2_level);
        }
        
        // 5秒写入一次
        vTaskDelay(pdMS_TO_TICKS(300000)); // 5秒
    }
}

// ================= ZigBee UART Task =================
static uint8_t zigbee_rx_buf[16];
void ZigBee_UART_Send(uint8_t *data, uint16_t len) {
    HAL_UART_Transmit(&huart6, data, len, 100);
}

// 新增：统一打包并发送传感器数据的函数
void ZigBee_SendSensorData(void) {
    extern SHT20_Data_t sht20_data;
    extern TVOC_CO2_Data_t tvoc_co2_data;
    uint8_t txbuf[10];
    int16_t temp = -999, humi = -999;
    uint16_t tvoc = 0, ch2o = 0, co2 = 0;

    // 只有数据有效时才打包真实数据
    if (sht20_data.data_valid) {
        temp = (int16_t)(sht20_data.temperature * 10);
        humi = (int16_t)(sht20_data.humidity * 10);
    }
    if (tvoc_co2_data.data_valid) {
        tvoc = ((uint16_t)tvoc_co2_data.tvoc_high << 8) | tvoc_co2_data.tvoc_low;
        ch2o = ((uint16_t)tvoc_co2_data.ch2o_high << 8) | tvoc_co2_data.ch2o_low;
        co2  = ((uint16_t)tvoc_co2_data.co2_high << 8) | tvoc_co2_data.co2_low;
    }

    // 打包数据（高字节在前，低字节在后）
    txbuf[0] = (uint8_t)(temp >> 8);
    txbuf[1] = (uint8_t)(temp & 0xFF);
    txbuf[2] = (uint8_t)(humi >> 8);
    txbuf[3] = (uint8_t)(humi & 0xFF);
    txbuf[4] = (uint8_t)(tvoc >> 8);
    txbuf[5] = (uint8_t)(tvoc & 0xFF);
    txbuf[6] = (uint8_t)(ch2o >> 8);
    txbuf[7] = (uint8_t)(ch2o & 0xFF);
    txbuf[8] = (uint8_t)(co2 >> 8);
    txbuf[9] = (uint8_t)(co2 & 0xFF);

    // 调试打印
    printf("[ZigBee] temp=%.2f humi=%.2f tvoc=%u ch2o=%u co2=%u\r\n", 
        sht20_data.temperature, sht20_data.humidity, tvoc, ch2o, co2);
    printf("[ZigBee] txbuf: ");
    for (int i = 0; i < 10; i++) printf("%02X ", txbuf[i]);
    printf("\r\n");

    ZigBee_UART_Send(txbuf, 10);
}

void ZigBee_UART_Task(void *argument) {
    for (;;) {
        // 定时打包并发送数据
        ZigBee_SendSensorData();
        vTaskDelay(pdMS_TO_TICKS(1000)); // 每秒发送一次
    }
}
/* USER CODE END Application */

